/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.gui.dialog;

import java.rmi.registry.Registry;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.opentcs.util.I18nCommon;
import org.opentcs.util.gui.Icons;

/**
 * A dialog that lets the user enter parameters for a connection to the portal.
 */
public class ConnectToServerDialog
    extends JDialog {

  /**
   * A return status code - returned if Cancel button has been pressed.
   */
  public static final int RET_CANCEL = 0;
  /**
   * A return status code - returned if OK button has been pressed.
   */
  public static final int RET_OK = 1;
  /**
   * This class's resource bundle.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nCommon.BUNDLE_PATH);
  /**
   * The connection's description.
   */
  private String description;
  /**
   * The host to connect to.
   */
  private String host;
  /**
   * The port to connect to.
   */
  private int port;
  /**
   * The list of connection param sets.
   */
  private final List<ConnectionParamSet> paramSets;
  /**
   * This dialog's return status code.
   */
  private int returnStatus = RET_CANCEL;

  /**
   * Creates a new instance.
   *
   * @param paramSets The list of connection param sets.
   */
  public ConnectToServerDialog(List<ConnectionParamSet> paramSets) {
    super((JFrame) null, true);
    this.paramSets = requireNonNull(paramSets, "paramSets");

    initComponents();
    initConnectionBookmarks();

    if (paramSets.isEmpty()) {
      description = "Localhost";
      host = "localhost";
      port = Registry.REGISTRY_PORT;
    }
    else {
      description = paramSets.get(0).getDescription();
      host = paramSets.get(0).getHost();
      port = paramSets.get(0).getPort();
    }

    textFieldDescription.setText(description);
    textFieldServer.setText(host);
    textFieldPort.setText(String.valueOf(port));
    getRootPane().setDefaultButton(okButton);

    setIconImages(Icons.getOpenTCSIcons());
    setLocationRelativeTo(null);
    pack();
  }

  public String getDescription() {
    return description;
  }

  public int getPort() {
    return port;
  }

  public String getHost() {
    return host;
  }

  /**
   * Returns the return status of this dialog.
   *
   * @return the return status of this dialog - one of {@link #RET_OK} or {@link #RET_CANCEL}.
   */
  public int getReturnStatus() {
    return returnStatus;
  }

  private void doClose(int retStatus) {
    returnStatus = retStatus;
    setVisible(false);
    dispose();
  }

  /**
   * Initializes connection bookmarks from the config file.
   */
  private void initConnectionBookmarks() {
    DefaultComboBoxModel<ConnectionParamSet> model
        = (DefaultComboBoxModel<ConnectionParamSet>) cbComboBox.getModel();

    for (ConnectionParamSet bookmark : paramSets) {
      model.addElement(bookmark);
    }
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    labelDescription = new javax.swing.JLabel();
    textFieldDescription = new javax.swing.JTextField();
    labelServer = new javax.swing.JLabel();
    textFieldServer = new javax.swing.JTextField();
    labelPort = new javax.swing.JLabel();
    textFieldPort = new javax.swing.JTextField();
    panelButtons = new javax.swing.JPanel();
    okButton = new javax.swing.JButton();
    cancelButton = new CancelButton();
    cbComboBox = new javax.swing.JComboBox<>();

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/common/Bundle"); // NOI18N
    setTitle(bundle.getString("connectToServerDialog.title")); // NOI18N
    getContentPane().setLayout(new java.awt.GridBagLayout());

    labelDescription.setFont(labelDescription.getFont());
    labelDescription.setText(bundle.getString("connectToServerDialog.label_description.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 4);
    getContentPane().add(labelDescription, gridBagConstraints);

    textFieldDescription.setColumns(15);
    textFieldDescription.setFont(textFieldDescription.getFont());
    textFieldDescription.setText("Localhost");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weighty = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 8);
    getContentPane().add(textFieldDescription, gridBagConstraints);

    labelServer.setFont(labelServer.getFont());
    labelServer.setText(bundle.getString("connectToServerDialog.label_host.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 4);
    getContentPane().add(labelServer, gridBagConstraints);

    textFieldServer.setColumns(15);
    textFieldServer.setFont(textFieldServer.getFont());
    textFieldServer.setText("localhost");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weighty = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 8);
    getContentPane().add(textFieldServer, gridBagConstraints);

    labelPort.setFont(labelPort.getFont());
    labelPort.setText(bundle.getString("connectToServerDialog.label_port.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 4);
    getContentPane().add(labelPort, gridBagConstraints);

    textFieldPort.setColumns(15);
    textFieldPort.setFont(textFieldPort.getFont());
    textFieldPort.setText("1099");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weighty = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 8);
    getContentPane().add(textFieldPort, gridBagConstraints);

    panelButtons.setLayout(new java.awt.GridBagLayout());

    okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() | java.awt.Font.BOLD));
    okButton.setText(bundle.getString("connectToServerDialog.button_ok.text")); // NOI18N
    okButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        okButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
    gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
    panelButtons.add(okButton, gridBagConstraints);

    cancelButton.setFont(cancelButton.getFont());
    cancelButton.setText(bundle.getString("connectToServerDialog.button_cancle.text")); // NOI18N
    cancelButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        cancelButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.gridwidth = 2;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
    gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
    panelButtons.add(cancelButton, gridBagConstraints);

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 4;
    gridBagConstraints.gridwidth = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_END;
    gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
    getContentPane().add(panelButtons, gridBagConstraints);

    cbComboBox.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    cbComboBox.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        cbComboBoxActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
    gridBagConstraints.weighty = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 8);
    getContentPane().add(cbComboBox, gridBagConstraints);

    pack();
  }// </editor-fold>//GEN-END:initComponents

  private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
    description = textFieldDescription.getText();
    if (description.isEmpty()) {
      JOptionPane.showMessageDialog(this,
                                    BUNDLE.getString("connectToServerDialog.optionPane_invalidDescription.message"),
                                    BUNDLE.getString("connectToServerDialog.optionPane_invalidDescription.title"),
                                    JOptionPane.ERROR_MESSAGE
      );
      return;
    }

    host = textFieldServer.getText();
    if (host.isEmpty()) {
      JOptionPane.showMessageDialog(this,
                                    BUNDLE.getString("connectToServerDialog.optionPane_invalidHost.message"),
                                    BUNDLE.getString("connectToServerDialog.optionPane_invalidHost.title"),
                                    JOptionPane.ERROR_MESSAGE
      );
      return;
    }

    try {
      port = Integer.parseInt(textFieldPort.getText());
      if (port < 0 || port > 65535) {
        throw new NumberFormatException();
      }
    }
    catch (NumberFormatException e) {
      JOptionPane.showMessageDialog(this,
                                    BUNDLE.getString("connectToServerDialog.optionPane_invalidPort.message"),
                                    BUNDLE.getString("connectToServerDialog.optionPane_invalidPort.title"),
                                    JOptionPane.ERROR_MESSAGE
      );
      return;
    }

    doClose(RET_OK);
  }//GEN-LAST:event_okButtonActionPerformed

  private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
    doClose(RET_CANCEL);
  }//GEN-LAST:event_cancelButtonActionPerformed

  private void cbComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbComboBoxActionPerformed
    DefaultComboBoxModel<ConnectionParamSet> model
        = (DefaultComboBoxModel<ConnectionParamSet>) cbComboBox.getModel();
    ConnectionParamSet cb = (ConnectionParamSet) model.getSelectedItem();

    if (cb != null) {
      textFieldDescription.setText(cb.getDescription());
      textFieldServer.setText(cb.getHost());
      textFieldPort.setText(String.valueOf(cb.getPort()));
    }
  }//GEN-LAST:event_cbComboBoxActionPerformed
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JButton cancelButton;
  private javax.swing.JComboBox<ConnectionParamSet> cbComboBox;
  private javax.swing.JLabel labelDescription;
  private javax.swing.JLabel labelPort;
  private javax.swing.JLabel labelServer;
  private javax.swing.JButton okButton;
  private javax.swing.JPanel panelButtons;
  private javax.swing.JTextField textFieldDescription;
  private javax.swing.JTextField textFieldPort;
  private javax.swing.JTextField textFieldServer;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}
